#include "AlgorithmStats.hpp"
#include "GraphExploration.hpp"
#include "GraphDatabase.hpp"
#include "GraphFunctions.hpp"
#include <algorithm>
#include <numeric>

// include headers that implement an archive
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>

// To serialize
#include <boost/serialization/vector.hpp>
#include <boost/serialization/set.hpp>
#include <boost/graph/adj_list_serialize.hpp>
#include <boost/serialization/utility.hpp> // For std::pair

#include <fstream>

using namespace std;
using namespace boost;
using namespace TopologicalLearner;

//----------------------------------------------------------------
void TestingSet::Save(string sFilename) const
{
    ofstream ofs(sFilename.c_str(), ios::binary);

    boost::archive::binary_oarchive oa(ofs);
    oa << (*this);
    ofs.close();
}
//----------------------------------------------------------------
void TestingSet::Load(string sFilename)
{
    std::ifstream ifs(sFilename.c_str(), ios::binary);


    boost::archive::binary_iarchive oa(ifs);
    oa >> (*this);

    ifs.close();
}
//----------------------------------------------------------------
void TestingSet::GenerateTestingSet(vector<unsigned int> PGSizes, const GraphDatabase& D)
{
    srand ( time(NULL) );

    //TestingSet kRes;

    int iTotalPGs = std::accumulate( PGSizes.begin(), PGSizes.end(), 0 );
    m_PGs.resize(iTotalPGs);
    m_PGSizes = PGSizes;

    int iID = 0;

    // For each partial graph size
    for(unsigned int i=1; i < PGSizes.size(); i++)
    {
        // Generate PGSizes[i] partial graphs of size i
        for(unsigned int k=0;k < PGSizes[i]; k++)
        {
            // Pick a random graph that has atleast i vertices
            int iGraphID; const Graph* pG = 0;
            while(pG == 0)
            {
                iGraphID = rand() % D.GetNumGraphs();
                //static int iGraphID = 0;
                if( num_vertices(D.GetGraph(iGraphID)) >= i )
                    pG = &D.GetGraph(iGraphID);
                //iGraphID = (iGraphID + 1) % D.GetNumGraphs();
            }

            // We've found a suitable graph, now select a random partial graph from it
            GraphExploration GE(*pG,D.IsUnique());


            GraphExploration::EditOpIterator it(GE);



            for(unsigned int j=1; j < i; j++)
            {

                // Add the other vertices in a random manner
                EditOp kTmp = it.NextVertexOp(false);
                *it;
            }

            // from main graph to partial graph
            map<Vertex,Vertex> tmpmap = GE.GetGraphMapping();
            map<Vertex,Vertex>::iterator itbegin;

            // revert the map so it's from partial graph --> main graph
            for(itbegin = tmpmap.begin(); itbegin != tmpmap.end(); ++itbegin ){
                m_partialToTestedGraphMap[iID][itbegin->second] = itbegin->first;
            }

            Graph G = GE.GetPartialGraph();
            assert( num_vertices(G) == i );

            m_PGs[iID] = make_pair(iGraphID, GE.GetPartialGraph());
            iID++;

        }

    }

}
